package net.csdn.business.common.utils;

import com.alibaba.fastjson2.JSONObject;
import net.csdn.business.common.domain.common.FieldCheck;
import net.csdn.business.common.enums.ResultCodeEnum;
import net.csdn.business.common.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字段配置检测相关配置
 *
 * @author likun
 * @date 2022/6/28 21:39
 */
public class FieldCheckUtil {

    /**
     * 通过 FieldCheck 配置解析 params body 体 --> key[FieldCheck.getKeyName()]、value结构
     * <code>
     * FieldCheck fieldCheck = new FieldCheck();
     * fieldCheck.setNotNull(Boolean.TRUE);
     * fieldCheck.setMinLength(2);
     * fieldCheck.setKey("$.name");
     * fieldCheck.setKeyName("name");
     * <p>
     * String body = "{\"name\":\"likun\",\"sex\":1}";
     * System.out.println(getValueByCheckFields(JsonUtil.toJsonObject(body), Lists.newArrayList(fieldCheck)));
     * <p>
     * <p>
     * ======result=======
     * {"name":"likun"}
     * </code>
     *
     * @param params      body
     * @param checkFields 字段
     * @return JSONObject
     */
    public static JSONObject getValueByCheckFields(JSONObject params, List<FieldCheck> checkFields) {
        JSONObject r = new JSONObject();
        if (CollectionUtils.isEmpty(checkFields)) {
            return r;
        }

        checkFields.forEach(ck -> r.putAll(getValueCheckField(params, ck)));
        return r;
    }

    public static JSONObject getValueCheckField(JSONObject params, FieldCheck check) throws BusinessException {
        String field = check.getKey();
        if (StringUtils.isEmpty(field)) {
            throw new BusinessException(ResultCodeEnum.CONFIG_ERROR, "FieldCheck");
        }

        Object value = JsonUtil.getValueByKey(params, check.getKey());

        String msg = "";
        boolean err = false;
        if (Boolean.TRUE.equals(check.getNotNull()) && value == null) {
            msg = "#{[field]}不能弄为空";
            err = true;
        }
        if (!err && Boolean.TRUE.equals(check.getIsNull()) && value != null) {
            msg = "#{[field]}不能设值";
            err = true;
        }
        if (!err && check.getMax() != null) {
            if (!isNumber(value)) {
                msg = "#{[field]}格式错误";
                err = true;
            } else if (Double.parseDouble(value.toString()) > check.getMax()) {
                msg = "#{[field]}不能超过#{[max]}";
                err = true;
            }
        }
        if (!err && check.getMin() != null) {
            if (!isNumber(value)) {
                msg = "#{[field]}格式不正确";
                err = true;
            } else if (Double.parseDouble(value.toString()) < check.getMin()) {
                msg = "#{[field]}不能小于#{[min]}";
                err = true;
            }

        }
        if (!err && check.getMaxLength() != null && value instanceof String && value.toString().length() > check.getMaxLength()) {
            msg = "#{[field]}不能超过#{[maxLength]}个字符";
            err = true;
        }
        if (!err && check.getMinLength() != null && value instanceof String && value.toString().length() < check.getMinLength()) {
            msg = "#{[field]}不能小于#{[minLength]}个字符";
            err = true;
        }
        if (!err && check.getRegex() != null && value instanceof String) {
            Pattern p = Pattern.compile(check.getRegex());
            Matcher m1 = p.matcher((String) value);
            boolean match = m1.matches();
            if (!match) {
                msg = "#{[field]}值不符合规则：#{[regex]}";
                err = true;
            }
        }
        if (err) {
            JSONObject param = JsonUtil.toJsonObject(check);
            param.put("field", field);
            if (StringUtils.isEmpty(msg)) {
                msg = check.getMessage();
            }
            String errMsg = StringTemplateUtil.parseTemplate(msg, param);
            ExceptionUtil.throwBizException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM, errMsg);
        }
        JSONObject r = new JSONObject();
        r.put(check.getKeyName(), value);
        return r;
    }

    public static boolean isNumber(Object value) {
        if (value == null) {
            return false;
        }
        return NumberUtils.isCreatable(value.toString());
    }
}